#include <Drivers/block/nand/nand_drv.h>
#include <os\ioapi\libblock\include\Blkdev.h>
#include <am_bl_ex.h>
#include <upgrade_img.h>
extern AMEBootPara boot_parameter;
#pragma WEAK _famres ext_res_s_dummy
#pragma WEAK _eamres ext_res_e_dummy
extern unsigned  extern_resource_list[];
extern unsigned extern_resource_size;
extern char _famres[];
extern char _eamres[];

unsigned ext_res_s=(unsigned)_famres;
unsigned ext_res_e=(unsigned)_eamres;


unsigned ext_res_s_dummy=0;
unsigned ext_res_e_dummy=0;
unsigned AWCheckExResource(unsigned addr)
{
	
	if (addr>=ext_res_s&&addr<ext_res_e)
		return 1;
	return 0;
}
unsigned AWGetExResourceLen(unsigned addr)
{
	
	unsigned i;
	unsigned a=0,b;
	unsigned target=addr-ext_res_s;
	b=(extern_resource_size);
	b=((extern_resource_size>>2)-1);
	if(target==extern_resource_list[0])
		return extern_resource_list[1];
	if(target==extern_resource_list[b])
		return ext_res_e-ext_res_s-extern_resource_list[b];
	while(a<b-1)
	{
		i=(a+b)>>1;
		if(target<extern_resource_list[i])
		{
			b=i;
		}else if(target==extern_resource_list[i])
		{
			return extern_resource_list[i+1]-extern_resource_list[i];
		}else{
			a=i;
		}
	}
	return 0;
}
extern SystemDescription system_desc;
extern AMEBootPara boot_parameter;
unsigned AWGetExResource(unsigned addr,unsigned len)
{
	
#ifndef IMAGE_BURNER
	return addr;
#else
	
	if (addr<ext_res_s||addr>=ext_res_e)
		return addr;
	if(boot_parameter.boot_device==NOR_SLOT_2)
	{
		return addr-ext_res_s+system_desc.device[2].offset+boot_parameter.res_offset+0x400000;
	}
	static int nand_fd=-1;
	static unsigned current=0;
	static unsigned cur_addr=0x0;
	static unsigned cur_size=0x0;
	
	if(nand_fd<0)
	{
		nand_fd=open((char*)GetBootDevice(),O_RDONLY);
		if(nand_fd<0)
			return 0;
	}
	unsigned target_addr=(addr-ext_res_s)+GetResourceOffset();
	if(current&&(target_addr>=cur_addr)&&((target_addr+len)<cur_addr+cur_size))
	{
		return (target_addr-cur_addr)+(unsigned)current;
	}
	
	unsigned max_read_size=0;
	if(current==0)
	{
		unsigned b,i;
		b=((extern_resource_size>>2)-1);
		max_read_size=ext_res_e-extern_resource_list[b]-ext_res_s;
		for(i=0;i<((extern_resource_size>>2)-1);i++)
		{
			if(max_read_size<extern_resource_list[i+1]-extern_resource_list[i])
				max_read_size=extern_resource_list[i+1]-extern_resource_list[i];
		}
		max_read_size+=4096;
		current=(unsigned)AVMem_malloc(max_read_size);
		cur_size=max_read_size;
		
	}
		
	
	if(current==0)
	{
		while(1);
		return 0;
	}
	
	lseek(nand_fd,target_addr,SEEK_SET);
	read(nand_fd,(void*)current,cur_size);
	cur_addr=target_addr;
	
	return (target_addr-cur_addr)+(unsigned)current;
#endif
}